using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.RepositoryFactory.SchemaDiscovery.ObjectModel.Base;

namespace Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.DbTypesHelperStrategies
{
   public sealed class MsOraDbTypesHelper : IDbTypesHelperStrategy
   {
      #region IDbTypesHelperStrategy Members

      public string GetGenericDBType(DatabaseType type)
      {
         switch (type)
         {
            case DatabaseType.BFile: return "OracleType.BFile"; // DbType does not support BFile
            case DatabaseType.BinaryDouble: return "DbType.Double";
            case DatabaseType.BinaryFloat: return "DbType.Single";
            case DatabaseType.Blob: return "OracleType.Blob"; // DbType does not support Blob
            case DatabaseType.Boolean: return " DbType.Boolean";
            case DatabaseType.Byte: return "DbType.Byte";
            case DatabaseType.Char: return "DbType.AnsiStringFixedLength";
            case DatabaseType.Clob: return "OracleType.Clob"; // DbType does not support Clob
            case DatabaseType.Cursor: return "OracleType.Cursor"; // DbType does not support Cursor
            case DatabaseType.Date: return "DbType.DateTime";
            case DatabaseType.Float: return "DbType.Single";
            case DatabaseType.Int32: return "DbType.Int32";
            case DatabaseType.IntervalDayToSecond: return "DbType.TimeSpan";
            case DatabaseType.IntervalYearToMonth: return "DbType.Int64";
            case DatabaseType.Long: return "DbType.AnsiString";
            case DatabaseType.LongRaw: return "DbType.Binary";
            case DatabaseType.NChar: return "DbType.StringFixedLength";
            case DatabaseType.NClob: return "OracleType.NClob"; // DbType does not support NClob
            case DatabaseType.Number: return "DbType.Decimal";
            case DatabaseType.NVarChar: return "DbType.String";
            case DatabaseType.Raw: return "DbType.Binary";
            case DatabaseType.Real: return "DbType.Decimal";
            // For the next 3 entries, keep in mind that the Oracle native Timestamp types can have
            // much greater precision.  When working with the .NET DateTime type, precision drops
            // to one third of a millisecond.
            case DatabaseType.Timestamp: return "DbType.DateTime";
            case DatabaseType.TimestampLocal: return "DbType.DateTime";
            case DatabaseType.TimestampWithTz: return "DbType.DateTime";
            case DatabaseType.VarChar: return "DbType.String";
            case DatabaseType.Xml: return "DbType.String"; // Though not formally documented, I inferred from ODP
            // documentation that a string would be acceptable
            default: return "DbType.Object";
         }
      }

      public string GetReaderMethod(DatabaseType type)
      {
         switch (type)
         {
            case DatabaseType.BFile: return "GetBytes";
            case DatabaseType.BinaryDouble: return "GetDouble";
            case DatabaseType.BinaryFloat: return "GetFloat";
            case DatabaseType.Blob: return "GetBytes";
            case DatabaseType.Boolean: return "GetBoolean";
            case DatabaseType.Byte: return "GetByte";
            case DatabaseType.Char: return "GetString";
            case DatabaseType.Clob: return "GetString";
            case DatabaseType.Date: return "GetDateTime";
            case DatabaseType.Float: return "GetFloat";
            case DatabaseType.Int32: return "GetInt32";
            case DatabaseType.IntervalDayToSecond: return "GetTimeSpan";
            case DatabaseType.IntervalYearToMonth: return "GetInt64";
            case DatabaseType.Long: return "GetString";
            case DatabaseType.LongRaw: return "GetBytes";
            case DatabaseType.NChar: return "GetString";
            case DatabaseType.NClob: return "GetString";
            case DatabaseType.Number: return "GetDecimal"; // biggest possible size given NUMBER Oracle type (note
            // that overflow is still possible because using .NET type.
            case DatabaseType.NVarChar: return "GetString";
            case DatabaseType.Raw: return "GetBytes";
            case DatabaseType.Real: return "GetDecimal";
            case DatabaseType.Timestamp: return "GetDateTime";
            case DatabaseType.TimestampLocal: return "GetDateTime";
            case DatabaseType.TimestampWithTz: return "GetDateTime";
            case DatabaseType.VarChar: return "GetString";
            case DatabaseType.Xml: return "GetString";
            default: return "//TODO No accessor found in GetReaderMethod(DatabaseType type)\n";
         }
      }

      public string GetClsType(DatabaseType type)
      {
         switch (type)
         {
            case DatabaseType.BFile: return "Byte[]";
            case DatabaseType.BinaryDouble: return "Double";
            case DatabaseType.BinaryFloat: return "Single";
            case DatabaseType.Blob: return "Byte[]";
            case DatabaseType.Boolean: return "Boolean";
            case DatabaseType.Byte: return "Byte";
            case DatabaseType.Char: return "String";
            case DatabaseType.Clob: return "String";
            case DatabaseType.Date: return "DateTime";
            case DatabaseType.Float: return "Double";
            case DatabaseType.Int64: return "Int64";
            case DatabaseType.Int32: return "Int32";
            case DatabaseType.Int16: return "Int16";
            case DatabaseType.NChar: return "String";
            case DatabaseType.NClob: return "String";
            case DatabaseType.Number: return "Decimal";
            case DatabaseType.NVarChar: return "String";
            case DatabaseType.Raw: return "Byte[]";
            case DatabaseType.Real: return "Decimal";
            case DatabaseType.Timestamp: return "DateTime";
            case DatabaseType.TimestampLocal: return "DateTime";
            case DatabaseType.TimestampWithTz: return "DateTime";
            case DatabaseType.VarChar: return "String";
            case DatabaseType.Xml: return "String";
            default: return "Object";
         }
      }

      public string GetProviderType(DatabaseType type)
      {
         switch (type)
         {
            case DatabaseType.BFile: return "OracleType.BFile";
            case DatabaseType.BinaryDouble: return "OracleType.Double";
            case DatabaseType.BinaryFloat: return "OracleType.Float";
            case DatabaseType.Blob: return "OracleType.Blob";
            case DatabaseType.Boolean: return "OracleType.VarChar";
            case DatabaseType.Byte: return "OracleType.Int16"; // close approximation
            case DatabaseType.Char: return "OracleType.Char";
            case DatabaseType.Clob: return "OracleType.Clob";
            case DatabaseType.Cursor: return "OracleType.Cursor";
            case DatabaseType.Date: return "OracleType.DateTime";
            case DatabaseType.Float: return "OracleType.Float";
            case DatabaseType.Int32: return "OracleType.Int32";
            case DatabaseType.IntervalDayToSecond: return "OracleType.IntervalDayToSecond";
            case DatabaseType.IntervalYearToMonth: return "OracleType.IntervalYearToMonth";
            case DatabaseType.Long: return "OracleType.Varchar"; //close approximation
            case DatabaseType.LongRaw: return "OracleType.LongRaw";
            case DatabaseType.NChar: return "OracleType.NChar";
            case DatabaseType.NClob: return "OracleType.NClob";
            case DatabaseType.Number: return "OracleType.Number";
            case DatabaseType.NVarChar: return "OracleType.NVarChar";
            case DatabaseType.Raw: return "OracleType.Raw";
            case DatabaseType.Real: return "OracleType.Number"; //close approximation
            case DatabaseType.Timestamp: return "OracleType.Timestamp";
            case DatabaseType.TimestampLocal: return "OracleType.TimestampLocal";
            case DatabaseType.TimestampWithTz: return "OracleType.TimestampWithTz";
            case DatabaseType.VarChar: return "OracleType.VarChar";
            case DatabaseType.Xml: return "OracleType.VarChar";
            default: return "OracleType.VarChar";
         }
      }

      #endregion
   }
}
